/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2016 All Rights Reserved.
 */
package com.singfan.core.dao;

import com.google.common.base.CaseFormat;
import com.google.common.collect.Lists;
import com.singfan.common.db.annotation.Primarykey;
import com.singfan.core.dao.database.model.*;
import com.singfan.core.dao.database.model.config.*;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * DbTableGenerator
 *
 * @author Cassius Cai
 * @version $Id: DbTableGenerator, v 0.1 3/19/16 11:15 Exp $
 */
public class DbTableGenerator {
    public static void main(String[] args) {
        List<Class> app = Lists.newArrayList(Barber.class, BarberAdditional.class,
            BarberAppointment.class, BarberComment.class, BarberHairstyle.class,
            BarberHairService.class, BarberToken.class, CouponRecord.class, Customer.class,
            CustomerCollect.class, CustomerCoupon.class, CustomerToken.class, JpushInfo.class,
            Manager.class, OrderPayChannelInfo.class, Orders.class, PhoneSecurityCode.class,
            Shop.class, ShopAdditional.class, ShopHair.class, ShopHairAppointmentDetail.class,
            ShopHairAppointmentSummary.class, ShopHairService.class, ShopHairSuit.class,
            ShopToken.class);

        List<Class> cfg = Lists.newArrayList(BarberPositionConfig.class,
            BusinessCircleConfig.class, CityConfig.class, DistrictConfig.class,
            MasterShopConfig.class, ProvinceConfig.class);

        String appSql = genMySQLSchema(app, "singfan_app.sql",
            Lists.newArrayList("singfan_app", "singfan_app_test"));
        String cfgSql = genMySQLSchema(cfg, "singfan_config.sql",
            Lists.newArrayList("singfan_config", "singfan_config_test"));
        System.out.println(appSql);
        System.out.println(cfgSql);
    }

    private static String genMySQLSchema(List<Class> classes, String fileName, List<String> dbNames) {
        StringBuffer sb = new StringBuffer();
        for (String dbName : dbNames) {
            for (Class clazz : classes) {
//                sb.append("DROP TABLE IF EXISTS " + dbName + "."
//                          + toDataBaseString(clazz.getSimpleName() + ";"));
                sb.append("CREATE TABLE " + dbName + "." + toDataBaseString(clazz.getSimpleName())
                          + "(");
                Field[] fields = clazz.getDeclaredFields();
                for (int i = 0; i < fields.length; i++) {
                    Field field = fields[i];
                    String mysqlField = toDataBaseString(field.getName()) + "  "
                                        + javaTypeToMysqlType(field);
                    if (field.getAnnotation(Primarykey.class) != null) {
                        mysqlField = mysqlField + " PRIMARY KEY NOT NULL AUTO_INCREMENT";
                    }

                    if (i != fields.length - 1) {
                        mysqlField = mysqlField + ",";
                    }
                    sb.append(mysqlField);
                }
                sb.append(");");
            }
        }
        return sb.toString();
    }

    private static String toDataBaseString(String fieldOrTable) {
        return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldOrTable);
    }

    private static String javaTypeToMysqlType(Field field) {
        Class<?> typeClass = field.getType();
        if (typeClass == String.class) {
            if (field.getName().toLowerCase().contains("desc")
                    || field.getName().toLowerCase().contains("img")
                    || field.getName().toLowerCase().contains("url")) {
                return "VARCHAR(5120)";
            } else {
                return "VARCHAR(512)";
            }
        }

        if (typeClass == boolean.class) {
            return "TINYINT(1)";
        }

        if (typeClass == long.class) {
            return "BIGINT(10)";
        }

        if (typeClass == Date.class) {
            return "DATETIME DEFAULT NOW()";
        }

        if (typeClass == int.class) {
            return "INTEGER(10)";
        }

        if (typeClass == BigDecimal.class) {
            return "DECIMAL(11,8)";
        }

        throw new RuntimeException("Undefined Type:" + typeClass.getSimpleName());
    }
}
